#ifndef __LIB_KFIFO
#define __LIB_KFIFO

#include <stdint.h>
#include <stdlib.h>

class kfifo {

private:
	enum class kfifo_state
	{
		KFIFO_EMPTY,
		KFIFO_FULL,
		/* 半满既不满也不空 */
		KFIFO_HALFFULL,
	};

	uint8_t* buffer_ptr;
	uint16_t read_mirror : 1;
	uint16_t read_index : 15;
	uint16_t write_mirror : 1;
	uint16_t write_index : 15;
	int16_t buffer_size;

	uint8_t init_flag;

	void init(uint8_t* data_ptr, uint16_t data_size);
	
	inline enum kfifo_state kfifo_status(void)
	{
		if (read_index == write_index)
		{
			if (read_mirror == write_mirror)
				return kfifo_state::KFIFO_EMPTY;
			else
				return kfifo_state::KFIFO_FULL;
		}
		return kfifo_state::KFIFO_HALFFULL;
	}

public:
	kfifo(uint16_t data_size = 512);
	kfifo(uint8_t* data_ptr, uint16_t data_size);
	~kfifo();

	size_t kfifo_put(const uint8_t* ptr, size_t length);
	size_t kfifo_put_force(const uint8_t* ptr, size_t length);
	size_t kfifo_get(uint8_t* ptr, size_t length);
	size_t kfifo_peek(uint8_t** ptr);
	size_t kfifo_putchar(const uint8_t ch);
	size_t kfifo_putchar_force(const uint8_t ch);
	size_t kfifo_getchar(uint8_t* ch);
	size_t kfifo_getchar_force(uint8_t* ch);

	size_t kfifo_data_len(void);
	size_t kfifo_data_space_len(void);

	void kfifo_reset(void);
};

#endif // !__LIB_KFIFO
